#include <string.h>
#include "sipsiparser.h"
#include "BuilderPlugin.h"
#include "buildersectioncontrol.h"

#define SDT_TIMEOUT			3	//seconds
#define PAT_PMT_TIMEOUT	1	//seconds

static builder_section_control_cfg_t stConfig = {BUILDER_SECTION_DATA_NOSDT_STOP, 1, 1};

//return 0-finish, -1-not finish
int PluginSecFinishCheck(unsigned char* pu8RecvBitmap, unsigned char u8LastSecNo, unsigned char u8CurSecNo)
{
	unsigned int i;
	int ret = 0;
	
	pu8RecvBitmap[u8CurSecNo] = 1;
	for(i=0; i<=u8LastSecNo; i++)
	{
		if(pu8RecvBitmap[i] != 1)
		{
			ret = -1;
			break;
		}
	}
	PluginDvbLogcat("PluginSecFinishCheck() - ret = %d\r\n", ret);
	
	return ret;
}

//return 0-received, 1-not received
int PluginSecRecvCheck(unsigned char* pu8RecvBitmap, unsigned char u8CurSecNo)
{
	PluginDvbLogcat("PluginSecRecvCheck() - pu8RecvBitmap[u8CurSecNo] = %x\r\n", pu8RecvBitmap[u8CurSecNo]);
				
	if(pu8RecvBitmap[u8CurSecNo] == 1)
		return 0;
	else
		return -1;
}

//return receive section count
int PluginSecRecvCount(unsigned char* pu8RecvBitmap, unsigned char u8LastSectionNum)
{
	int i = 0,count = 0;
	PluginDvbLogcat("PluginSecRecvCount() - pu8RecvBitmap[u8LastSectionNum] = %x\r\n", pu8RecvBitmap[u8LastSectionNum]);
	for (i=0; i <= u8LastSectionNum; i++) {	
		if(pu8RecvBitmap[i] == 1)
			count++;
	}
	return count;
}

int PluginAddPatSection(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section)
{
	int s32Ret = -1;
	builder_section_t* pstSection;

	PluginDvbLogcat("PluginAddPatSection() - entry\r\n");
	s32Ret = PluginCreatSectionNode(&pstSection, pu8Section);
	if(s32Ret == 0)
	{
		pstSection->m_pstNext = pstSectionRecvCntrl->m_stSiPsi.m_pstPat;
		pstSectionRecvCntrl->m_stSiPsi.m_pstPat = pstSection;
	}	
	PluginDvbLogcat("PluginAddPatSection() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginAddPmtSection(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section)
{
	int s32Ret = -1;
	builder_section_t* pstSection;

	PluginDvbLogcat("PluginAddPmtSection() - entry\r\n");
	s32Ret = PluginCreatSectionNode(&pstSection, pu8Section);
	if(s32Ret == 0)
	{
		pstSection->m_pstNext = pstSectionRecvCntrl->m_stSiPsi.m_pstPmt;
		pstSectionRecvCntrl->m_stSiPsi.m_pstPmt = pstSection;
	}	
	PluginDvbLogcat("PluginAddPmtSection() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginAddSdtSection(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section)
{
	int s32Ret = -1;
	builder_section_t* pstSection;

	PluginDvbLogcat("PluginAddSdtSection() - entry\r\n");
	s32Ret = PluginCreatSectionNode(&pstSection, pu8Section);
	if(s32Ret == 0)
	{
		pstSection->m_pstNext = pstSectionRecvCntrl->m_stSiPsi.m_pstSdt;
		pstSectionRecvCntrl->m_stSiPsi.m_pstSdt = pstSection;
	}	
	PluginDvbLogcat("PluginAddSdtSection() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
	
}

static int PluginSectionDataRecvPat(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	unsigned char au8Data[16];
	unsigned char au8Mask[16];

	PluginDvbLogcat("PluginSectionDataRecvPat() - entry\r\n");
	memset(au8Data, 0, sizeof(au8Data));
	memset(au8Mask, 0, sizeof(au8Mask));
	au8Data[0] = SIPSI_TID_PAT;
	au8Mask[0] = 0xFF;
	s32Ret = PluginDvbSetFilter(&pstSectionRecvCntrl->m_u32Filter, SIPSI_PID_PAT, au8Data, au8Mask, 1);
	if(s32Ret == 0)
	{
		pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
		PluginDvbLogcat("PluginSectionDataRecvPat() - set filter OK, pstSectionRecvCntrl->m_u32Filter = %x\r\n", pstSectionRecvCntrl->m_u32Filter);
	}
	else
	{
		pstSectionRecvCntrl->m_u32Filter = BUILDER_INVALID_FILTER;
		PluginDvbLogcat("PluginSectionDataRecvPat() - set filter error\r\n");
	}
	PluginDvbLogcat("PluginSectionDataRecvPat() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

static int PluginSectionDataRecvPmt(builder_section_control_t* pstSectionRecvCntrl, unsigned short u16PmtPid, unsigned short u16ServiceId)
{
	int s32Ret = -1;
	unsigned char au8Data[16];
	unsigned char au8Mask[16];
	unsigned int u32Slot = 0;

	PluginDvbLogcat("PluginSectionDataRecvPmt() - entry, u16PmtPid = %d, u16ServiceId = %d\r\n", u16PmtPid, u16ServiceId);

	for(u32Slot=0; u32Slot<PMT_RECV_FILTER_MAX_NUM; u32Slot++)
	{
		if(pstSectionRecvCntrl->m_au32PmtFilter[u32Slot] == BUILDER_INVALID_FILTER)
			break;
	}
	
	if(u32Slot<PMT_RECV_FILTER_MAX_NUM)
	{
		memset(au8Data, 0, sizeof(au8Data));
		memset(au8Mask, 0, sizeof(au8Mask));
		au8Data[0] = SIPSI_TID_PMT;
		au8Mask[0] = 0xFF;
		au8Data[3] = (unsigned char)((u16ServiceId>>8)&0xFF);
		au8Data[4] = (unsigned char)(u16ServiceId&0xFF);
		au8Mask[3] = 0xFF;
		au8Mask[4] = 0xFF;
		s32Ret = PluginDvbSetFilter(&pstSectionRecvCntrl->m_au32PmtFilter[u32Slot], u16PmtPid, au8Data, au8Mask, 5);
		if(s32Ret == 0)
		{
			pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
			pstSectionRecvCntrl->m_au32PmtTimeout[u32Slot] = PAT_PMT_TIMEOUT*stConfig.m_u16PSITimeoutRatio;
			PluginDvbLogcat("PluginSectionDataRecvPmt() - set filter OK, pstSectionRecvCntrl->m_au32PmtFilter[u32Slot = %d] = %x\r\n", u32Slot, pstSectionRecvCntrl->m_au32PmtFilter[u32Slot]);
		}
		else
		{
			pstSectionRecvCntrl->m_au32PmtFilter[u32Slot] = BUILDER_INVALID_FILTER;
			PluginDvbLogcat("PluginSectionDataRecvPmt() - set filter error\r\n");
		}
	}
	PluginDvbLogcat("PluginSectionDataRecvPmt() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataStopPmtFilter(builder_section_control_t* pstSectionRecvCntrl, unsigned int u32Filter)
{
	int s32Ret = -1;
	unsigned int u32Slot = 0;

	PluginDvbLogcat("PluginSectionDataStopPmtFilter() - entry. pstSectionRecvCntrl = %p, u32Filter = 0x%x\r\n", pstSectionRecvCntrl, u32Filter);
	if(pstSectionRecvCntrl)
	{
		for(u32Slot=0; u32Slot<PMT_RECV_FILTER_MAX_NUM; u32Slot++)
		{
			if(pstSectionRecvCntrl->m_au32PmtFilter[u32Slot] == u32Filter)
				break;
		}

		if(u32Slot<PMT_RECV_FILTER_MAX_NUM)
		{
			s32Ret = PluginDvbReleaseFilter(pstSectionRecvCntrl->m_au32PmtFilter[u32Slot]);
			pstSectionRecvCntrl->m_au32PmtFilter[u32Slot] = BUILDER_INVALID_FILTER;
		}
		else
		{
			PluginDvbLogcat("PluginSectionDataStopPmtFilter() - filter not found\r\n");
			s32Ret = 0;
		}
	}
	PluginDvbLogcat("PluginSectionDataStopPmtFilter() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataGetPmtFilterInprocessCnt(builder_section_control_t* pstSectionRecvCntrl, unsigned int* pu32Cnt)
{
	int s32Ret = -1;
	unsigned int u32Slot;
	unsigned int u32Cnt = 0;

	PluginDvbLogcat("PluginSectionDataGetPmtFilterInprocessCnt() - entry. pstSectionRecvCntrl = %p, pu32Cnt = %p\r\n", pstSectionRecvCntrl, pu32Cnt);
	if(pstSectionRecvCntrl && pu32Cnt)
	{
		for(u32Slot=0; u32Slot<PMT_RECV_FILTER_MAX_NUM; u32Slot++)
		{
			if(pstSectionRecvCntrl->m_au32PmtFilter[u32Slot] != BUILDER_INVALID_FILTER)
				u32Cnt++;
		}
		*pu32Cnt = u32Cnt;
		s32Ret = 0;
	}
	PluginDvbLogcat("PluginSectionDataGetPmtFilterInprocessCnt() - return, u32Cnt = %d, s32Ret = %d\r\n", u32Cnt, s32Ret);

	return s32Ret;
}


static int PluginSectionDataRecvSdt(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	unsigned char au8Data[16];
	unsigned char au8Mask[16];

	PluginDvbLogcat("PluginSectionDataRecvSdt() - entry\r\n");
	memset(au8Data, 0, sizeof(au8Data));
	memset(au8Mask, 0, sizeof(au8Mask));
	au8Data[0] = SIPSI_TID_SDT_ACTUAL;
	au8Mask[0] = 0xFF;
	s32Ret = PluginDvbSetFilter(&pstSectionRecvCntrl->m_u32Filter, SIPSI_PID_SDTBAT, au8Data, au8Mask, 1);
	if(s32Ret == 0)
	{
		pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
		PluginDvbLogcat("PluginSectionDataRecvSdt() - set filter OK, pstSectionRecvCntrl->m_u32Filter = %x\r\n", pstSectionRecvCntrl->m_u32Filter);
	}
	else
	{
		pstSectionRecvCntrl->m_u32Filter = BUILDER_INVALID_FILTER;
		PluginDvbLogcat("PluginSectionDataRecvSdt() - set filter error\r\n");
	}
	PluginDvbLogcat("PluginSectionDataRecvSdt() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataStopFilter(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;

	PluginDvbLogcat("PluginSectionDataStopFilter() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	PluginDvbLogcat("PluginSectionDataStopFilter() - pstSectionRecvCntrl->m_u32Filter = %d\r\n", pstSectionRecvCntrl->m_u32Filter);
	if(pstSectionRecvCntrl && pstSectionRecvCntrl->m_u32Filter != BUILDER_INVALID_FILTER)
	{
		s32Ret = PluginDvbReleaseFilter(pstSectionRecvCntrl->m_u32Filter);
		pstSectionRecvCntrl->m_u32Filter = BUILDER_INVALID_FILTER;
	}
	PluginDvbLogcat("PluginSectionDataStopFilter() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataHandleSdt(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section)
{
	int s32Ret = -1;
	unsigned char u8SecNo;
	unsigned char u8LastSecNo;

	PluginDvbLogcat("PluginSectionDataHandleSdt() - entry. pstSectionRecvCntrl = %p, pu8Section = %p\r\n", pstSectionRecvCntrl, pu8Section);
	if(pstSectionRecvCntrl && pu8Section)
	{
		if(pstSectionRecvCntrl->m_eType == BUILDER_RECV_SDT)
		{
			pstSectionRecvCntrl->m_u32RecvDataTimes++;
			u8SecNo = SiPsiGetSectionNo(pu8Section);
			u8LastSecNo = SiPsiGetLastSectionNo(pu8Section);
			if(PluginSecRecvCheck(pstSectionRecvCntrl->m_au8SecRecvBitmap, u8SecNo) != 0)//not recieved
			{
				unsigned short u16SecLen;

				u16SecLen = SiPsiGetSectionLength(pu8Section);
				PluginDvbLogcat("PluginSectionDataHandleSdt() - receive SDT, sec[%d], lastSec[%d], crc[0x%x%x%x%x]\r\n", pu8Section[6], pu8Section[7], 
					pu8Section[u16SecLen-4], pu8Section[u16SecLen-3], pu8Section[u16SecLen-2], pu8Section[u16SecLen-1]);
				s32Ret = PluginAddSdtSection(pstSectionRecvCntrl, pu8Section);
				if(PluginSecFinishCheck(pstSectionRecvCntrl->m_au8SecRecvBitmap, u8LastSecNo, u8SecNo) == 0)//finish, start pat
				{
					PluginSectionDataStopFilter(pstSectionRecvCntrl);
					PluginSectionDataRecvPat(pstSectionRecvCntrl);
					pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
					pstSectionRecvCntrl->m_eType = BUILDER_RECV_PAT;
					pstSectionRecvCntrl->m_u32Timeout = PAT_PMT_TIMEOUT*stConfig.m_u16PSITimeoutRatio;
				}
			}
			else
			{
				PluginDvbLogcat("PluginSectionDataHandleSdt() - receive SDT, sec[%d], lastSec[%d], again\r\n", pu8Section[6], pu8Section[7]);
			}

			if(pstSectionRecvCntrl->m_u32RecvDataTimes >= (u8LastSecNo+1)*2)//not finish, continue recv pat
			{
				PluginSectionDataStopFilter(pstSectionRecvCntrl);
				PluginSectionDataRecvPat(pstSectionRecvCntrl);
				pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
				pstSectionRecvCntrl->m_eType = BUILDER_RECV_PAT;
				pstSectionRecvCntrl->m_u32Timeout = PAT_PMT_TIMEOUT*stConfig.m_u16PSITimeoutRatio;
			}
		}
		else
		{
			PluginDvbLogcat("PluginSectionDataHandleSdt() - state is not sdt, pstSectionRecvCntrl->m_eType = %d\r\n", pstSectionRecvCntrl->m_eType);
		}
	}
	PluginDvbLogcat("PluginSectionDataHandleSdt() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataHandlePat(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section)
{
	int s32Ret = -1;
	unsigned short u16ProgNum;
	unsigned short u16Pid;
	sipsi_program_t stProgram;

	PluginDvbLogcat("PluginSectionDataHandlePat() - entry. pstSectionRecvCntrl = %p, pu8Section = %p\r\n", pstSectionRecvCntrl, pu8Section);
	if(pstSectionRecvCntrl && pu8Section)
	{
		if(pstSectionRecvCntrl->m_eType == BUILDER_RECV_PAT)
		{
			pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
			PluginSectionDataStopFilter(pstSectionRecvCntrl);
			PluginAddPatSection(pstSectionRecvCntrl, pu8Section);
			u16ProgNum = SiPsiPATGetProgramCount(pu8Section);
			PluginDvbLogcat("PluginSectionDataHandlePat() - find program count= %d\r\n", u16ProgNum);
			if(u16ProgNum)
			{
				pstSectionRecvCntrl->m_u32PmtIndex = 0;
				do
				{
					SiPsiPATGetProgram(pu8Section, &stProgram, pstSectionRecvCntrl->m_u32PmtIndex);
					if(stProgram.m_u16ProgNum == 0)//nit
					{
						pstSectionRecvCntrl->m_u32PmtIndex++;
						if(pstSectionRecvCntrl->m_u32PmtIndex < u16ProgNum)
						{	
							SiPsiPATGetProgram(pu8Section, &stProgram, pstSectionRecvCntrl->m_u32PmtIndex);
							s32Ret = PluginSectionDataRecvPmt(pstSectionRecvCntrl, stProgram.m_u16PmtPid, stProgram.m_u16ProgNum);
							if(s32Ret == 0)
								pstSectionRecvCntrl->m_u32PmtIndex++;
							pstSectionRecvCntrl->m_eType = BUILDER_RECV_PMT;
							
						}
						else//only one program, nit
						{
							PluginDvbLogcat("PluginSectionDataHandlePat() - pat found not program\r\n");
							pstSectionRecvCntrl->m_eType = BUILDER_RECV_PMT;
						}
					}
					else
					{
						s32Ret = PluginSectionDataRecvPmt(pstSectionRecvCntrl, stProgram.m_u16PmtPid, stProgram.m_u16ProgNum);
						if(s32Ret == 0)
								pstSectionRecvCntrl->m_u32PmtIndex++;
						pstSectionRecvCntrl->m_eType = BUILDER_RECV_PMT;	
					}
				}while(pstSectionRecvCntrl->m_u32PmtIndex<u16ProgNum && s32Ret != -1);
				s32Ret = 0;
			}
			else
			{
				PluginDvbLogcat("PluginSectionDataHandlePat() - pat no program\r\n");
				pstSectionRecvCntrl->m_u32PmtIndex = 0;
				s32Ret = 0;
			}
		}
		else
		{
			PluginDvbLogcat("PluginSectionDataHandlePat() - state is not sdt, pstSectionRecvCntrl->m_eType = %d\r\n", pstSectionRecvCntrl->m_eType);
		}

	}
	PluginDvbLogcat("PluginSectionDataHandlePat() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataHandlePmt(builder_section_control_t* pstSectionRecvCntrl, unsigned char* pu8Section, unsigned int hFilter)
{
	int s32Ret = -1;
	unsigned short u16ProgNum;
	unsigned short u16Pid;
	sipsi_program_t stProgram;

	PluginDvbLogcat("PluginSectionDataHandlePmt() - entry. pstSectionRecvCntrl = %p, pu8Section = %p\r\n", pstSectionRecvCntrl, pu8Section);
	if(pstSectionRecvCntrl && pu8Section)
	{
		if(pstSectionRecvCntrl->m_eType == BUILDER_RECV_PMT)
		{
			pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
			s32Ret = PluginSectionDataStopPmtFilter(pstSectionRecvCntrl, hFilter);
			if(s32Ret != -1)
			{
				PluginAddPmtSection(pstSectionRecvCntrl, pu8Section);
				u16ProgNum = SiPsiPATGetProgramCount(pstSectionRecvCntrl->m_stSiPsi.m_pstPat->m_au8Section);
				s32Ret = 0;
				if(u16ProgNum > pstSectionRecvCntrl->m_u32PmtIndex)
				{
					PluginDvbLogcat("PluginSectionDataHandlePmt() - receive next, pstSectionRecvCntrl->m_u32PmtIndex = %d\r\n", pstSectionRecvCntrl->m_u32PmtIndex);
					SiPsiPATGetProgram(pstSectionRecvCntrl->m_stSiPsi.m_pstPat->m_au8Section, &stProgram, pstSectionRecvCntrl->m_u32PmtIndex);
					PluginSectionDataRecvPmt(pstSectionRecvCntrl, stProgram.m_u16PmtPid, stProgram.m_u16ProgNum);
					pstSectionRecvCntrl->m_u32PmtIndex++;
				}
				else
				{
					PluginDvbLogcat("PluginSectionDataHandlePmt() - pmt recv finish\r\n");
				}
			}
			else
			{
				PluginDvbLogcat("PluginSectionDataHandlePmt() - pmt may have receive\r\n");
			}
		}
		else
		{
			PluginDvbLogcat("PluginSectionDataHandlePmt() - state is not pmt, pstSectionRecvCntrl->m_eType = %d\r\n", pstSectionRecvCntrl->m_eType);
		}

	}
	PluginDvbLogcat("PluginSectionDataHandlePmt() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

/***********************************************************************************/
/*********************************export API bellow***********************************/
/***********************************************************************************/

int PluginSectionDataStart(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginSectionDataStart() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	if(pstSectionRecvCntrl)
	{
		s32Ret = PluginSectionDataReset(pstSectionRecvCntrl);
		if(s32Ret == 0)
		{
			pstSectionRecvCntrl->m_eType = BUILDER_RECV_SDT;
			s32Ret = PluginSectionDataRecvSdt(pstSectionRecvCntrl);
			memset(pstSectionRecvCntrl->m_au8SecRecvBitmap, 0, sizeof(pstSectionRecvCntrl->m_au8SecRecvBitmap));
			pstSectionRecvCntrl->m_u32Timeout = SDT_TIMEOUT*stConfig.m_u16SITimeoutRatio;
		}
		else
		{
			PluginDvbLogcat("PluginSectionDataStart() - PluginSectionDataReset return error\r\n");
		}
	}
	PluginDvbLogcat("PluginSectionDataStart() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataTimeOut(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;

	PluginDvbLogcat("PluginSectionDataTimeOut() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	s32Ret = PluginSectionDataStop(pstSectionRecvCntrl);
	PluginDvbLogcat("PluginSectionDataTimeOut() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

int PluginSectionDataTick(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	unsigned short u16ProgNum;
	unsigned short u16Pid;
	sipsi_program_t stProgram;
	
	PluginDvbLogcat("PluginSectionDataTick() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	if(pstSectionRecvCntrl->m_eType == BUILDER_RECV_PMT)
	{
		unsigned int i;

		for(i=0; i<PMT_RECV_FILTER_MAX_NUM; i++)
		{
			if(pstSectionRecvCntrl->m_au32PmtFilter[i] != BUILDER_INVALID_FILTER)
			{
				if(pstSectionRecvCntrl->m_au32PmtTimeout[i] > 0)
				{
					pstSectionRecvCntrl->m_au32PmtTimeout[i]--;
					if(pstSectionRecvCntrl->m_au32PmtTimeout[i] == 0)
					{
						s32Ret = PluginDvbReleaseFilter(pstSectionRecvCntrl->m_au32PmtFilter[i]);
						pstSectionRecvCntrl->m_au32PmtFilter[i] = BUILDER_INVALID_FILTER;
						u16ProgNum = SiPsiPATGetProgramCount(pstSectionRecvCntrl->m_stSiPsi.m_pstPat->m_au8Section);
						s32Ret = 0;
						if(u16ProgNum > pstSectionRecvCntrl->m_u32PmtIndex)
						{
							PluginDvbLogcat("PluginSectionDataTick() - receive next, pstSectionRecvCntrl->m_u32PmtIndex = %d\r\n", pstSectionRecvCntrl->m_u32PmtIndex);
							SiPsiPATGetProgram(pstSectionRecvCntrl->m_stSiPsi.m_pstPat->m_au8Section, &stProgram, pstSectionRecvCntrl->m_u32PmtIndex);
							PluginSectionDataRecvPmt(pstSectionRecvCntrl, stProgram.m_u16PmtPid, stProgram.m_u16ProgNum);
							pstSectionRecvCntrl->m_u32PmtIndex++;
						}
						else
						{
							PluginDvbLogcat("PluginSectionDataTick() - pmt recv finish\r\n");
						}
					}
				}
			}
		}
	}
	else
	{
		if(pstSectionRecvCntrl->m_u32Timeout > 0)
		{
			s32Ret = 0;
			pstSectionRecvCntrl->m_u32Timeout--;
			if(pstSectionRecvCntrl->m_u32Timeout==0 && pstSectionRecvCntrl->m_eType==BUILDER_RECV_SDT && stConfig.m_eSecRecvCfg==BUILDER_SECTION_DATA_NOSDT_CONTINUE)
			{
				PluginDvbLogcat("PluginSectionDataTick() - recv sdt timeout, continue recv pat pmt!\r\n");
				PluginSectionDataStopFilter(pstSectionRecvCntrl);
				PluginSectionDataRecvPat(pstSectionRecvCntrl);
				pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
				pstSectionRecvCntrl->m_eType = BUILDER_RECV_PAT;
				pstSectionRecvCntrl->m_u32Timeout = PAT_PMT_TIMEOUT*stConfig.m_u16PSITimeoutRatio;
				s32Ret = 0;
			}
			else if(pstSectionRecvCntrl->m_u32Timeout==0)
			{
				PluginDvbLogcat("PluginSectionDataTick() - recv sdt timeout, stop filter!\r\n");
				PluginSectionDataStopFilter(pstSectionRecvCntrl);
			}
		}
	}
	PluginDvbLogcat("PluginSectionDataTick() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}


int PluginSectionDataRecv(builder_section_control_t* pstSectionRecvCntrl, unsigned int hFilter, unsigned char* pu8Section)
{
	int s32Ret = -1;
	unsigned char u8TableId;
	
	PluginDvbLogcat("PluginSectionDataRecv() - entry. pstSectionRecvCntrl = %p, hFilter = %x, pu8Section = %p\r\n", pstSectionRecvCntrl, hFilter, pu8Section);
	if(pstSectionRecvCntrl->m_eType==BUILDER_RECV_PMT || hFilter==pstSectionRecvCntrl->m_u32Filter)
	{
		u8TableId = pu8Section[0];
		switch(u8TableId)
		{
			case SIPSI_TID_SDT_ACTUAL:
				s32Ret = PluginSectionDataHandleSdt(pstSectionRecvCntrl, pu8Section);
				break;
			case SIPSI_TID_PAT:
				s32Ret = PluginSectionDataHandlePat(pstSectionRecvCntrl, pu8Section);
				break;
			case SIPSI_TID_PMT:
				s32Ret = PluginSectionDataHandlePmt(pstSectionRecvCntrl, pu8Section, hFilter);
				break;
			default:
				PluginDvbLogcat("PluginSectionDataRecv() - recv error table id\r\n");
				break;
		}
	}
	else
	{
		s32Ret = 0;
		PluginDvbLogcat("PluginSectionDataRecv() - pstSectionRecvCntrl->m_u32Filter = 0x%x, not equal hFilter\r\n", pstSectionRecvCntrl->m_u32Filter);
	}
	PluginDvbLogcat("PluginSectionDataRecv() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataGetProcess(builder_section_control_t* pstSectionRecvCntrl, unsigned int* pu32Process)
{
	unsigned char u8Percentage = 0;
	int s32Ret = -1;
	unsigned int u32SdtSectionCnt = 0;
	unsigned int u32SdtSectionRecvCnt = 0;
	builder_section_t* pstSectionNode;
	unsigned short u16ProgNum;
	unsigned int u32PmtRecvingCnt = 0;

	PluginDvbLogcat("PluginSectionDataGetProcess() - entry. pstSectionRecvCntrl = %p, pu8Process = %p\r\n", pstSectionRecvCntrl, pu32Process);
	if(pstSectionRecvCntrl && pu32Process)
	{
		if(pstSectionRecvCntrl->m_stSiPsi.m_pstPat)//pat ok
		{
			pstSectionNode = pstSectionRecvCntrl->m_stSiPsi.m_pstPat;
			if(pstSectionNode)
			{
				u16ProgNum = SiPsiPATGetProgramCount(pstSectionNode->m_au8Section);
				if(u16ProgNum > 0)
				{
					u8Percentage = 40;
					PluginSectionDataGetPmtFilterInprocessCnt(pstSectionRecvCntrl, &u32PmtRecvingCnt);
					u8Percentage += 60*(pstSectionRecvCntrl->m_u32PmtIndex-u32PmtRecvingCnt)/u16ProgNum;
				}
				else
				{
					u8Percentage = 100;
				}
			}
			PluginDvbLogcat("PluginSectionDataGetProcess() - u8Percentage = %d\r\n", u8Percentage);
		}
		else if(pstSectionRecvCntrl->m_stSiPsi.m_pstSdt)//sdt 40%
		{
			pstSectionNode = pstSectionRecvCntrl->m_stSiPsi.m_pstSdt;
			u32SdtSectionCnt = SiPsiGetLastSectionNo(pstSectionNode->m_au8Section)+1;
			while(pstSectionNode)
			{
				pstSectionNode = pstSectionNode->m_pstNext;
				u32SdtSectionRecvCnt++;
			}
			
			if(u32SdtSectionCnt < u32SdtSectionRecvCnt)
			{
				PluginDvbLogcat("PluginSectionDataGetProcess() - recv cnt > section cnt\r\n");
			}
			else
			{
				u8Percentage = 40*u32SdtSectionRecvCnt/u32SdtSectionCnt;
			}
		}
		*pu32Process = u8Percentage;
		s32Ret = 0;
	}
	PluginDvbLogcat("PluginSectionDataGetProcess() - return, u8Percentage = %d, s32Ret = %d\r\n", u8Percentage, s32Ret);
	return s32Ret;
}

int PluginSectionDataStop(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginSectionDataStop() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	if(pstSectionRecvCntrl)
	{
		s32Ret = PluginSectionDataReset(pstSectionRecvCntrl);
	}
	else
	{
		PluginDvbLogcat("PluginSectionDataStop() - recv error parameter\r\n");
	}
	PluginDvbLogcat("PluginSectionDataStop() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginSectionDataReset(builder_section_control_t* pstSectionRecvCntrl)
{
	int s32Ret = -1;
	unsigned int i;
	
	PluginDvbLogcat("PluginSectionDataReset() - entry. pstSectionRecvCntrl = %p\r\n", pstSectionRecvCntrl);
	if(pstSectionRecvCntrl)
	{
		s32Ret = 0;
		if(pstSectionRecvCntrl->m_stSiPsi.m_pstSdt)
		{
			PluginFreeTable(pstSectionRecvCntrl->m_stSiPsi.m_pstSdt);
			pstSectionRecvCntrl->m_stSiPsi.m_pstSdt = NULL;
		}
		
		if(pstSectionRecvCntrl->m_stSiPsi.m_pstPat)
		{
			PluginFreeTable(pstSectionRecvCntrl->m_stSiPsi.m_pstPat);
			pstSectionRecvCntrl->m_stSiPsi.m_pstPat = NULL;
		}

		if(pstSectionRecvCntrl->m_stSiPsi.m_pstPmt)
		{
			PluginFreeTable(pstSectionRecvCntrl->m_stSiPsi.m_pstPmt);
			pstSectionRecvCntrl->m_stSiPsi.m_pstPmt = NULL;
		}

		if(pstSectionRecvCntrl->m_u32Filter!= BUILDER_INVALID_FILTER)
		{
			PluginDvbReleaseFilter(pstSectionRecvCntrl->m_u32Filter);
			pstSectionRecvCntrl->m_u32Filter = BUILDER_INVALID_FILTER;
		}
		pstSectionRecvCntrl->m_u32PmtIndex = 0;
		pstSectionRecvCntrl->m_u32RecvDataTimes = 0;
		pstSectionRecvCntrl->m_u32Timeout = 0;
		memset(pstSectionRecvCntrl->m_au8SecRecvBitmap, 0, sizeof(pstSectionRecvCntrl->m_au8SecRecvBitmap));
		memset(pstSectionRecvCntrl->m_au32PmtTimeout, 0, sizeof(pstSectionRecvCntrl->m_au32PmtTimeout));
		for(i=0; i<sizeof(pstSectionRecvCntrl->m_au32PmtFilter)/sizeof(pstSectionRecvCntrl->m_au32PmtFilter[0]); i++)
		{
			if(pstSectionRecvCntrl->m_au32PmtFilter[i] != BUILDER_INVALID_FILTER)
			{
				PluginDvbReleaseFilter(pstSectionRecvCntrl->m_au32PmtFilter[i]);
				pstSectionRecvCntrl->m_au32PmtFilter[i] = BUILDER_INVALID_FILTER;
			}
		}

	}
	PluginDvbLogcat("PluginSectionDataReset() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

//get data mallocated this module, please free outsize
int PluginSectionDataGetSections(builder_section_control_t* pstSectionRecvCntrl, builder_sipsi_t* pstSiPsi)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginSectionDataGetSections() - entry. pstSectionRecvCntrl = %p, pstSiPsi = %p\r\n", pstSectionRecvCntrl, pstSiPsi);
	if(pstSectionRecvCntrl && pstSiPsi)
	{
		s32Ret = 0;
		pstSiPsi->m_pstSdt = pstSectionRecvCntrl->m_stSiPsi.m_pstSdt;
		pstSectionRecvCntrl->m_stSiPsi.m_pstSdt = NULL;
		pstSiPsi->m_pstPat = pstSectionRecvCntrl->m_stSiPsi.m_pstPat;
		pstSectionRecvCntrl->m_stSiPsi.m_pstPat = NULL;
		pstSiPsi->m_pstPmt = pstSectionRecvCntrl->m_stSiPsi.m_pstPmt;
		pstSectionRecvCntrl->m_stSiPsi.m_pstPmt = NULL;
	}
	PluginDvbLogcat("PluginSectionDataGetSections() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;

}

int PluginSectionDataSetConfig(builder_section_control_t* pstSectionRecvCntrl, builder_section_control_cfg_t* pstCfg)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginSectionDataSetConfig() - entry. pstSectionRecvCntrl = %p, pstCfg = %p\r\n", pstSectionRecvCntrl, pstCfg);
	if(pstSectionRecvCntrl)
	{
		memcpy(&stConfig, pstCfg, sizeof(*pstCfg));
		s32Ret = 0;
	}
	PluginDvbLogcat("PluginSectionDataSetConfig() - return, s32Ret = %d\r\n", s32Ret);

	return s32Ret;
}

